<template>
  <div class="class-label-editor">
    <a-alert
      message="类别标签配置"
      type="info"
      show-icon
      style="margin-bottom: 16px"
    >
      <template #description>
        <div>配置YOLO模型输出的类别ID与物体名称的对应关系。</div>
        <div>• 类别ID: 范围0-9999,点击编辑按钮可修改</div>
        <div>• 类别名称: 长度不超过31个字符</div>
      </template>
    </a-alert>

    <div class="editor-header">
      <a-space>
        <a-button type="primary" @click="handleAddClass">
          <template #icon><plus-outlined /></template>
          添加类别
        </a-button>
        <a-dropdown>
          <template #overlay>
            <a-menu @click="handleLoadTemplate">
              <a-menu-item key="coco80">
                <file-text-outlined />
                COCO 80类
              </a-menu-item>
              <a-menu-item key="voc20">
                <file-text-outlined />
                VOC 20类
              </a-menu-item>
              <a-menu-item key="clear">
                <delete-outlined />
                清空所有
              </a-menu-item>
            </a-menu>
          </template>
          <a-button>
            快捷模板
            <down-outlined />
          </a-button>
        </a-dropdown>
        <a-button @click="handleImportJSON">
          <template #icon><upload-outlined /></template>
          导入JSON
        </a-button>
        <a-button @click="handleExportJSON">
          <template #icon><download-outlined /></template>
          导出JSON
        </a-button>
      </a-space>
      <a-tag color="blue">总计: {{ classLabels.length }} 类</a-tag>
    </div>

    <a-table
      :dataSource="classLabels"
      :columns="columns"
      :pagination="pagination"
      @change="handleTableChange"
      rowKey="id"
      :scroll="{ y: 400 }"
    >
      <template #bodyCell="{ column, record, index }">
        <template v-if="column.key === 'id'">
          <a-input-number
            v-if="editingKey === record.id"
            v-model:value="editingId"
            :min="0"
            :max="9999"
            :precision="0"
            @pressEnter="handleSave(record)"
            style="width: 100%"
          />
          <a-tag v-else color="blue">{{ record.id }}</a-tag>
        </template>
        <template v-else-if="column.key === 'name'">
          <a-input
            v-if="editingKey === record.id"
            v-model:value="editingName"
            :maxlength="31"
            @pressEnter="handleSave(record)"
            style="width: 100%"
          />
          <span v-else class="editable-cell-text">{{ record.name }}</span>
        </template>
        <template v-else-if="column.key === 'actions'">
          <a-space>
            <a-button
              v-if="editingKey !== record.id"
              type="link"
              size="small"
              @click="handleEdit(record)"
            >
              <template #icon><edit-outlined /></template>
            </a-button>
            <a-button
              v-else
              type="link"
              size="small"
              @click="handleSave(record)"
            >
              <template #icon><check-outlined /></template>
            </a-button>
            <a-button
              v-if="editingKey === record.id"
              type="link"
              size="small"
              @click="handleCancelEdit"
            >
              <template #icon><close-outlined /></template>
            </a-button>
            <a-button
              type="link"
              danger
              size="small"
              @click="handleDelete(record, index)"
            >
              <template #icon><delete-outlined /></template>
            </a-button>
          </a-space>
        </template>
      </template>
    </a-table>

    <!-- JSON导入对话框 -->
    <a-modal
      v-model:visible="importModalVisible"
      title="导入JSON"
      @ok="handleImportOk"
      @cancel="importModalVisible = false"
      width="600px"
    >
      <a-alert
        message="JSON格式要求"
        type="info"
        show-icon
        style="margin-bottom: 16px"
      >
        <template #description>
          <div>支持两种格式:</div>
          <div>1. 对象格式: {"0": "person", "1": "bicycle", ...}</div>
          <div>2. 数组格式: ["person", "bicycle", ...]</div>
        </template>
      </a-alert>
      <a-textarea
        v-model:value="importJSONText"
        placeholder='例如: {"0": "person", "1": "bicycle", "2": "car"}'
        :rows="10"
        :maxlength="10000"
        show-count
      />
    </a-modal>

    <!-- 文件输入(隐藏) -->
    <input
      ref="fileInputRef"
      type="file"
      accept=".json"
      style="display: none"
      @change="handleFileChange"
    />
  </div>
</template>

<script>
import { defineComponent, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import {
  PlusOutlined,
  EditOutlined,
  DeleteOutlined,
  CheckOutlined,
  CloseOutlined,
  UploadOutlined,
  DownloadOutlined,
  FileTextOutlined,
  DownOutlined
} from '@ant-design/icons-vue';

// COCO 80类标签模板
const COCO_80_CLASSES = [
  "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat",
  "traffic light", "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat",
  "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", "backpack",
  "umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", "sports ball",
  "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", "tennis racket",
  "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
  "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair",
  "couch", "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse",
  "remote", "keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator",
  "book", "clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush"
];

// VOC 20类标签模板
const VOC_20_CLASSES = [
  "aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow",
  "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa",
  "train", "tvmonitor"
];

export default defineComponent({
  name: 'ClassLabelEditor',
  components: {
    PlusOutlined,
    EditOutlined,
    DeleteOutlined,
    CheckOutlined,
    CloseOutlined,
    UploadOutlined,
    DownloadOutlined,
    FileTextOutlined,
    DownOutlined
  },
  props: {
    modelValue: {
      type: Array,
      default: () => []
    }
  },
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    // 状态管理
    const classLabels = ref([]);
    const editingKey = ref(-1);
    const editingId = ref(0);
    const editingName = ref('');
    const importModalVisible = ref(false);
    const importJSONText = ref('');
    const fileInputRef = ref(null);

    const pagination = ref({
      current: 1,
      pageSize: 20,
      total: 0,
      showSizeChanger: true,
      pageSizeOptions: ['10', '20', '50', '100'],
      showTotal: (total) => `总共 ${total} 类`
    });

    // 表格列定义
    const columns = [
      {
        title: '类别ID',
        key: 'id',
        dataIndex: 'id',
        width: 100,
        sorter: (a, b) => a.id - b.id
      },
      {
        title: '类别名称',
        key: 'name',
        dataIndex: 'name',
        ellipsis: true
      },
      {
        title: '操作',
        key: 'actions',
        width: 120,
        fixed: 'right'
      }
    ];

    // 初始化数据
    // modelValue可能是数组["person", "bicycle"]或对象{"0": "person", "1": "bicycle"}
    if (props.modelValue) {
      if (Array.isArray(props.modelValue)) {
        // 数组格式:转换为内部格式
        classLabels.value = props.modelValue.map((name, index) => ({
          id: index,
          name: name
        }));
      } else if (typeof props.modelValue === 'object') {
        // 对象格式:转换为内部格式
        classLabels.value = Object.entries(props.modelValue).map(([id, name]) => ({
          id: parseInt(id),
          name: name
        }));
        // 按ID排序
        classLabels.value.sort((a, b) => a.id - b.id);
      }
    }

    // 更新总数
    const updateTotal = () => {
      pagination.value.total = classLabels.value.length;
    };
    updateTotal();

    // 验证类别名称
    const validateName = (name) => {
      if (!name || name.trim() === '') {
        message.error('类别名称不能为空');
        return false;
      }
      if (name.length > 31) {
        message.error('类别名称长度不能超过31个字符');
        return false;
      }
      return true;
    };

    // 发射更新事件
    const emitUpdate = () => {
      // 将内部格式转换为后端需要的数组格式 ["person", "bicycle", ...]
      // 按ID排序,索引即为ID
      const sortedLabels = [...classLabels.value].sort((a, b) => a.id - b.id);

      // 构建数组,确保索引与ID对应
      const labelsArray = [];
      sortedLabels.forEach(item => {
        labelsArray[item.id] = item.name;
      });

      // 填充空值为空字符串(如果ID不连续)
      for (let i = 0; i < labelsArray.length; i++) {
        if (labelsArray[i] === undefined) {
          labelsArray[i] = "";
        }
      }

      emit('update:modelValue', labelsArray);
    };

    // 添加类别
    const handleAddClass = () => {
      const newId = classLabels.value.length > 0
        ? Math.max(...classLabels.value.map(item => item.id)) + 1
        : 0;

      classLabels.value.push({
        id: newId,
        name: `class_${newId}`
      });

      updateTotal();
      emitUpdate();
      message.success('添加成功');
    };

    // 编辑类别
    const handleEdit = (record) => {
      editingKey.value = record.id;
      editingId.value = record.id;
      editingName.value = record.name;
    };

    // 保存编辑
    const handleSave = (record) => {
      if (editingKey.value === -1) return;

      if (!validateName(editingName.value)) {
        return;
      }

      // 验证ID有效性
      if (editingId.value < 0 || editingId.value > 9999) {
        message.error('类别ID必须在0-9999范围内');
        return;
      }

      // 检查ID冲突(排除当前记录)
      const idConflict = classLabels.value.find(
        item => item.id === editingId.value && item.id !== record.id
      );
      if (idConflict) {
        message.error(`类别ID ${editingId.value} 已被"${idConflict.name}"使用`);
        return;
      }

      const index = classLabels.value.findIndex(item => item.id === record.id);
      if (index !== -1) {
        classLabels.value[index].id = editingId.value;
        classLabels.value[index].name = editingName.value.trim();
        emitUpdate();
        message.success('保存成功');
      }

      editingKey.value = -1;
      editingId.value = 0;
      editingName.value = '';
    };

    // 取消编辑
    const handleCancelEdit = () => {
      editingKey.value = -1;
      editingId.value = 0;
      editingName.value = '';
    };

    // 删除类别
    const handleDelete = (record, index) => {
      Modal.confirm({
        title: '确认删除',
        content: `确定要删除类别"${record.name}"(ID: ${record.id})吗?`,
        okText: '确认',
        okType: 'danger',
        cancelText: '取消',
        onOk: () => {
          classLabels.value.splice(index, 1);
          updateTotal();
          emitUpdate();
          message.success('删除成功');
        }
      });
    };

    // 加载模板
    const handleLoadTemplate = ({ key }) => {
      if (key === 'clear') {
        Modal.confirm({
          title: '确认清空',
          content: '确定要清空所有类别标签吗?',
          okText: '确认',
          okType: 'danger',
          cancelText: '取消',
          onOk: () => {
            classLabels.value = [];
            updateTotal();
            emitUpdate();
            message.success('已清空');
          }
        });
        return;
      }

      const template = key === 'coco80' ? COCO_80_CLASSES : VOC_20_CLASSES;
      const templateName = key === 'coco80' ? 'COCO 80类' : 'VOC 20类';

      Modal.confirm({
        title: '确认加载模板',
        content: `确定要加载${templateName}模板吗? 当前数据将被覆盖!`,
        okText: '确认',
        okType: 'warning',
        cancelText: '取消',
        onOk: () => {
          classLabels.value = template.map((name, index) => ({
            id: index,
            name: name
          }));
          updateTotal();
          emitUpdate();
          message.success(`已加载${templateName}模板`);
        }
      });
    };

    // 导入JSON
    const handleImportJSON = () => {
      fileInputRef.value.click();
    };

    // 处理文件选择
    const handleFileChange = (event) => {
      const file = event.target.files[0];
      if (!file) return;

      const reader = new FileReader();
      reader.onload = (e) => {
        importJSONText.value = e.target.result;
        importModalVisible.value = true;
      };
      reader.onerror = () => {
        message.error('文件读取失败');
      };
      reader.readAsText(file);

      // 清空input,允许重复选择同一文件
      event.target.value = '';
    };

    // 确认导入
    const handleImportOk = () => {
      try {
        const data = JSON.parse(importJSONText.value);
        let newLabels = [];

        if (Array.isArray(data)) {
          // 数组格式: ["person", "bicycle", ...]
          newLabels = data.map((name, index) => ({
            id: index,
            name: String(name).trim()
          }));
        } else if (typeof data === 'object') {
          // 对象格式: {"0": "person", "1": "bicycle", ...}
          newLabels = Object.entries(data).map(([id, name]) => ({
            id: parseInt(id),
            name: String(name).trim()
          }));
          // 按ID排序
          newLabels.sort((a, b) => a.id - b.id);
        } else {
          throw new Error('不支持的JSON格式');
        }

        // 验证
        for (const item of newLabels) {
          if (!validateName(item.name)) {
            return;
          }
        }

        classLabels.value = newLabels;
        updateTotal();
        emitUpdate();
        importModalVisible.value = false;
        importJSONText.value = '';
        message.success(`成功导入 ${newLabels.length} 个类别`);
      } catch (error) {
        message.error('JSON格式错误: ' + error.message);
      }
    };

    // 导出JSON
    const handleExportJSON = () => {
      if (classLabels.value.length === 0) {
        message.warning('没有可导出的数据');
        return;
      }

      // 按ID排序
      const sortedLabels = [...classLabels.value].sort((a, b) => a.id - b.id);

      // 构建数组格式,索引即为ID
      const exportData = [];
      sortedLabels.forEach(item => {
        exportData[item.id] = item.name;
      });

      // 填充空值为空字符串(如果ID不连续)
      for (let i = 0; i < exportData.length; i++) {
        if (exportData[i] === undefined) {
          exportData[i] = "";
        }
      }

      const jsonStr = JSON.stringify(exportData, null, 2);
      const blob = new Blob([jsonStr], { type: 'application/json' });
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href = url;
      link.download = 'class_labels.json';
      link.style.display = 'none';
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(url);

      message.success('导出成功');
    };

    // 表格分页变化
    const handleTableChange = (pag) => {
      pagination.value.current = pag.current;
      pagination.value.pageSize = pag.pageSize;
    };

    return {
      classLabels,
      editingKey,
      editingId,
      editingName,
      importModalVisible,
      importJSONText,
      fileInputRef,
      pagination,
      columns,
      handleAddClass,
      handleEdit,
      handleSave,
      handleCancelEdit,
      handleDelete,
      handleLoadTemplate,
      handleImportJSON,
      handleExportJSON,
      handleFileChange,
      handleImportOk,
      handleTableChange
    };
  }
});
</script>

<style scoped>
.class-label-editor {
  padding: 0;
}

.editor-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.editable-cell-text {
  padding: 4px 11px;
  display: block;
}

:deep(.ant-table) {
  font-size: 14px;
}

:deep(.ant-btn-link) {
  padding: 4px 8px;
}
</style>
